package top.superflow.flow.config.parse

import org.apache.commons.lang3.builder.ToStringBuilder
import top.superflow.exception.{InitException, RequestUnsupportedException}
import top.superflow.flow.config.parse.center.GlobalParserCenter
import top.superflow.flow.config.parse.impl.FlowConfigParser
import top.superflow.flow.config.process.ProcessConfig
import top.superflow.flow.config.process.provider.ProcessProviderConfig
import top.superflow.flow.config.{Config, FlowConfig, ResourceConfig}
import top.superflow.flow.mapper.MapperConfig
import top.superflow.flow.runtime.context.GlobalContext
import top.superflow.log.Loggable

class FlowConfigParserFactory extends Loggable{

  private var globalContext : GlobalContext = _

  private def getGlobalContext : GlobalContext = globalContext

  private def setGlobalContext (g : GlobalContext) = globalContext = g




  def getParserFromCenter[C <: Config](config: C): Parser[_] = {

    val originalParser = GlobalParserCenter.getInstance.getParser(config)

    if (originalParser == null) {
      throw new RequestUnsupportedException("There is no corresponding parser for the config [" + ToStringBuilder.reflectionToString(originalParser) + "]")
    }

    originalParser
  }

  def getParser(request: Any): Parser[_] = {
    var parser: Parser[_ ] = null

    logger.info(ToStringBuilder.reflectionToString(request))
    request match {
      case option: Option[_] if (option != None) => {

        parser = getParser(option.get)
      }
      case flowConfig: FlowConfig => {
        parser = new FlowConfigParser
      }

      case resourceConfig: ResourceConfig => {
        parser = getParserFromCenter(resourceConfig)
      }

      case processProviderConfig: ProcessProviderConfig => {
        parser = getParserFromCenter(processProviderConfig)
      }

      case processConfig: ProcessConfig => {
        parser = getParserFromCenter(processConfig)
      }

      case mapperConfig: MapperConfig => {
        parser = getParserFromCenter(mapperConfig)
      }

      case _ => {
        throw new RequestUnsupportedException(request)
      }
    }

    parser
  }

}


object FlowConfigParserFactory {

  private val instance = new FlowConfigParserFactory


  def getInstance: FlowConfigParserFactory = {
    validateInit

    instance
  }

  private def validateInit {
    if(instance.getGlobalContext == null){
      throw new InitException("Please set GlobalContext by FlowConfigParserFactory.init and then use it.")
    }
  }

  def init(g : GlobalContext) = {
    instance.setGlobalContext(g)
  }


}